/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package laba8;
 import java.io.File;
 import java.io.FileFilter;
 import java.io.FileNotFoundException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
 public class ClassFinder {
 
     private final static String CLASS_EXT = ".class";
 
     private static ClassFinder classFinder;
 
     private List<Class> loadedClasses = new ArrayList<Class>();
     private URLClassLoader classLoader;
     private File root;
 
     public static ClassFinder getInctance() {
         if (classFinder == null) {
             classFinder = new ClassFinder();
         }
         return classFinder;
     }
 
     private ClassFinder() {
     }
 
     public void load(String rootFolder) throws Exception {
         File root = new File(rootFolder);
         if (root.exists()) {
             this.root = root;
             loadedClasses.clear();
             classLoader = new URLClassLoader(new URL[] { root.toURL() },
                     getClass().getClassLoader());
             load(root);
         } else {
             throw new FileNotFoundException("folder \"" + rootFolder
                     + "\" not exists");
         }
     }
 
     private void load(File file) throws Exception {
         for (File item : file.listFiles(new ExtFileFilter(CLASS_EXT))) {
             if (item.isDirectory()) {
                 load(item);
             } else {
                 try {
                     loadClass(item);
                 } catch (FileNotFoundException e) {
                     e.printStackTrace();
                 }
             }
         }
     }
 
     private void loadClass(File file) throws FileNotFoundException {
         String path = file.getAbsolutePath();
         path = path.substring(root.getAbsolutePath().length() + 1);
         path = path.substring(0, path.length() - CLASS_EXT.length());
         path = path.replaceAll("\\" + File.separator, ".");
 
         if (!file.isFile() || !file.getName().endsWith(CLASS_EXT))
             throw new FileNotFoundException("It is bad file: " + file);
 
         try {
             Class clazz = null;
             try {
                 clazz = getClass().getClassLoader().loadClass(path);
             }catch (ClassNotFoundException e) {
                 clazz = classLoader.loadClass(path);
             }
             loadedClasses.add(clazz);
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         }
     }
 
     public List<Class> find(Class clazz) {
         List<Class> classList = new ArrayList<Class>();
         for (Class item : loadedClasses) {
             if (Utils.isChild(clazz, item))
                 classList.add(item);
         }
         return classList;
     }
 
 
     private class ExtFileFilter implements FileFilter {
         private String ext;
 
         public ExtFileFilter(String ext) {
             this.ext = ext;
         }
 
         public boolean accept(File pathname) {
             return pathname.isDirectory()
                     || pathname.getAbsolutePath().endsWith(ext);
         }
     }
 }
